package com.yjz.jvm.juc.ExecutorService;

import com.alibaba.ttl.threadpool.TtlExecutors;
import org.slf4j.MDC;

import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author xiaofeijin
 * @createTime 2020-07-22 2:29 PM
 * @description 公共的现成执行器
 *     <p>目前线程池有使用到核心估价下单后置逻辑，所以使用之前建议先评估会不会由于线程不够用而影响线上正常业务
 */
public class BizExecutorsUtils {

  private static final AtomicInteger THREAD_NUM = new AtomicInteger(1);
  public static final ExecutorService EXECUTOR;
  private static final ThreadFactory THREAD_FACTORY;
  private static final String APPLICATION_BIZ_NAME = "biz-executor";

  static {
    /*
     这个地方是初始化线程工厂
    */
    THREAD_FACTORY =
        r -> {
          Thread t =
              new Thread(
                  null, r, APPLICATION_BIZ_NAME + "-pool-" + THREAD_NUM.getAndIncrement(), 0);
          if (t.isDaemon()) {
            t.setDaemon(false);
          }
          if (t.getPriority() != Thread.NORM_PRIORITY) {
            t.setPriority(Thread.NORM_PRIORITY);
          }
          return t;
        };
    /*
     这个是异步执行的线程池
    */
    EXECUTOR =
        TtlExecutors.getTtlExecutorService(
            new ThreadPoolExecutor(
                10,
                20,
                5L,
                TimeUnit.MINUTES,
                new LinkedBlockingQueue<>(1024),
                THREAD_FACTORY,
                new ThreadPoolExecutor.CallerRunsPolicy()) {
              @Override
              public void execute(Runnable command) {
                super.execute(wrapperThread(command));
              }
            });
  }

  private static Runnable wrapperThread(Runnable runnable) {
    final Map<String, String> ctx = MDC.getCopyOfContextMap();
    return () -> {
      if (ctx != null) {
        MDC.setContextMap(ctx);
      }
      try {
        runnable.run();
      } finally {
        // 线程使用了之后要清理
        MDC.clear();
      }
    };
  }
}
